import axios from 'axios'
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import API_BASE_URL from '../../conf'
import router from '@/router'

// 全局返回类型由 env.d.ts 提供：interface ApiResponse<T>

const instance = axios.create({
  baseURL: API_BASE_URL,
  timeout: 15000,
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
  },
})

// 内存中的令牌状态与设置方法
let authToken: string | null = null
export function setAuthHeader(token: string | null) {
  authToken = token
  if (token) {
    instance.defaults.headers.common.Authorization = `Bearer ${token}`
    localStorage.setItem('token', token)
  } else {
    delete instance.defaults.headers.common.Authorization
    localStorage.removeItem('token')
  }
}

// 初始化应用时，如本地存在 token 则设置一次
const persisted = localStorage.getItem('token')
if (persisted) setAuthHeader(persisted)

// 请求拦截器：此处不再改动 headers，默认头由 setAuthHeader 维护
instance.interceptors.request.use((config) => {
  return config
})

// 响应拦截器：401 统一跳转登录并清理令牌
instance.interceptors.response.use(
  (resp) => resp,
  (error: AxiosError) => {
    const status = error.response?.status
    if (status === 401) {
      // 清空令牌并跳转登录页
      setAuthHeader(null)
      if (router.currentRoute.value?.name !== 'login') {
        router.replace({ name: 'login' })
      }
    }
    return Promise.reject(error)
  },
)

function normalizeResponse<T>(resp: AxiosResponse<unknown>): ApiResponse<T> {
  const payload = resp?.data
  if (payload && typeof payload === 'object') {
    const p = payload as Record<string, unknown>
    const code = typeof p.code === 'number' ? (p.code as number) : resp.status
    const message = typeof p.message === 'string' ? (p.message as string) : resp.statusText
    const data = (p.data as T | null) ?? null
    const timestamp = typeof p.timestamp === 'string' ? (p.timestamp as string) : undefined
    return { code, message, data, timestamp }
  }
  return {
    code: resp.status,
    message: resp.statusText,
    data: null,
  }
}

function normalizeError<T>(error: AxiosError): ApiResponse<T> {
  const status = error.response?.status ?? 0
  const statusText = error.response?.statusText ?? 'Network Error'
  // 尝试从后端错误体中解析
  const payload = error.response?.data
  if (payload && typeof payload === 'object') {
    const p = payload as Record<string, unknown>
    const code = typeof p.code === 'number' ? (p.code as number) : status
    const message = typeof p.message === 'string' ? (p.message as string) : statusText
    const data = (p.data as T | null) ?? null
    const timestamp = typeof p.timestamp === 'string' ? (p.timestamp as string) : undefined
    return { code, message, data, timestamp }
  }
  return { code: status, message: statusText, data: null }
}

async function get<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
  try {
    const resp = await instance.get(url, config)
    return normalizeResponse<T>(resp)
  } catch (err) {
    return normalizeError<T>(err as AxiosError)
  }
}

async function post<TReq, TResp>(
  url: string,
  data?: TReq,
  config?: AxiosRequestConfig,
): Promise<ApiResponse<TResp>> {
  try {
    const resp = await instance.post(url, data, config)
    return normalizeResponse<TResp>(resp)
  } catch (err) {
    return normalizeError<TResp>(err as AxiosError)
  }
}

async function put<TReq, TResp>(
  url: string,
  data?: TReq,
  config?: AxiosRequestConfig,
): Promise<ApiResponse<TResp>> {
  try {
    const resp = await instance.put(url, data, config)
    return normalizeResponse<TResp>(resp)
  } catch (err) {
    return normalizeError<TResp>(err as AxiosError)
  }
}

async function patch<TReq, TResp>(
  url: string,
  data?: TReq,
  config?: AxiosRequestConfig,
): Promise<ApiResponse<TResp>> {
  try {
    const resp = await instance.patch(url, data, config)
    return normalizeResponse<TResp>(resp)
  } catch (err) {
    return normalizeError<TResp>(err as AxiosError)
  }
}

async function del<TResp>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<TResp>> {
  try {
    const resp = await instance.delete(url, config)
    return normalizeResponse<TResp>(resp)
  } catch (err) {
    return normalizeError<TResp>(err as AxiosError)
  }
}

export const http = { get, post, put, patch, del }
export default http
